package com.ums.upos.service;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.text.TextUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.printer.AlignEnum;
import com.nexgo.oaf.apiv3.device.printer.GrayLevelEnum;
import com.ums.upos.GlobalDataHolder;
import com.ums.upos.uapi.ServiceResult;
import com.ums.upos.uapi.device.printer.FeedUnit;
import com.ums.upos.uapi.device.printer.FontFamily;
import com.ums.upos.uapi.device.printer.OnPrintListener;
import com.ums.upos.uapi.device.printer.Printer;
import com.ums.upos.uapi.device.printer.PrinterConfig;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 打印服务类
 * Created by xiaox on 15-10-7.
 */
public class PrinterBinder extends Printer.Stub {
    private final String TAG = "PrinterService";
    private volatile boolean startPrintIsRunning = false;
    private Logger log;
    private com.nexgo.oaf.apiv3.device.printer.Printer sdkPrinter;
    private boolean isCutpaper = true;
    private Context context;
    private final BatteryManager batteryManager;
    private  int battery;

    PrinterBinder(Context context) {
        this.context = context;
        log = LoggerFactory.getLogger(TAG);
        sdkPrinter = GlobalDataHolder.getInstance().getDeviceEngine().getPrinter();
        batteryManager = (BatteryManager)context.getSystemService(context.BATTERY_SERVICE);
    }

    /**
     * 打印机初始化(initPrinter)
     */
    @Override
    public int initPrinter() throws RemoteException {
        log.info("call initPrinter");
        try {

            //mhl20171019 防止应用层重复调用导致服务崩溃
            if (startPrintIsRunning) {
                log.error("initPrinter busy");
                return ServiceResult.Printer_Busy;
            } else {
                sdkPrinter.initPrinter();
                return ServiceResult.Success;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    /**
     * 设置打印机参数
     * @param bundle 各厂家打印机参数信息（见 PrinterConfig 类定义）
     */
    @Override
    public void setConfig(Bundle bundle) throws RemoteException {
        log.info("call setConfig");
        try {
            int gray = 1;
            if (bundle != null) {
                for (String str : bundle.keySet()) {
                    log.debug("key {},value {}", str, bundle.get(str));

                    switch (str) {
                        case PrinterConfig.COMMON_GRAYLEVEL:
                            gray = bundle.getInt(PrinterConfig.COMMON_GRAYLEVEL);
                            if (gray < 30) {
                                sdkPrinter.setGray(GrayLevelEnum.LEVEL_0);
                            } else if (gray < 60) {
                                sdkPrinter.setGray(GrayLevelEnum.LEVEL_1);
                            } else {
                                sdkPrinter.setGray(GrayLevelEnum.LEVEL_2);
                            }
                            break;
                        case PrinterConfig.COMMON_IS_CUTPAPER:
                            isCutpaper = bundle.getBoolean(PrinterConfig.COMMON_IS_CUTPAPER);
                            break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 开始打印(startPrint)
     * @param listener 打印结果监听实例
     */
    @Override
    public int startPrint(final OnPrintListener listener) throws RemoteException {
        log.info("call startPrint");
        if (listener == null) return ServiceResult.Param_In_Invalid;
        if (startPrintIsRunning) {
            log.error("startPrint, printer busy");
            listener.onPrintResult(ServiceResult.Printer_Busy);
            return ServiceResult.Success;
        }
        int result = sdkPrinter.startPrint(isCutpaper, new com.nexgo.oaf.apiv3.device.printer.OnPrintListener() {
            @Override
            public void onPrintResult(int i) {
                try {
                    startPrintIsRunning = false;
                    listener.onPrintResult(convertStatus(i));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        if (result == SdkResult.Success) {
            startPrintIsRunning = true;
        }
        return convertStatus(result);
    }

    private int convertStatus(int state) {
        int result;
        switch (state) {
            case SdkResult.Success:
                result = ServiceResult.Success;
                break;
            case SdkResult.Printer_UnFinished:
                result = ServiceResult.Printer_UnFinished;
                break;
            case SdkResult.Printer_PaperLack:
                result = ServiceResult.Printer_PaperLack;
                break;
            case SdkResult.Printer_TooHot:
                result = ServiceResult.Printre_TooHot;
                break;
            default:
                result = ServiceResult.Printer_Print_Fail;
                break;
        }
        log.debug("call convertStatus,state:{},result:{}", state, result);
        return result;
    }

    /**
     * 获取当前打印机状态
     */
    @Override
    public int getStatus() throws RemoteException {
        log.info("call getStatus");
        try {
/*            battery = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
            if(battery<25){
                return ServiceResult.Printer_Low_Power;
            }*/

            //此时如果缺纸，直接返回3  不会像以前那样返回 2了 ，因此返回3 缺纸   4 过热，  无需循环检测,5电量低
            if (startPrintIsRunning) return ServiceResult.Printer_Busy;
            int result = sdkPrinter.getStatus();
            log.debug("getStatus result:{}", result);
            result = convertStatus(result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    /**
     * 设置打印文字数据
     * @param text       打印数据
     * @param fontsize   字体
     * (以目前银商总公司银行卡程序大中小字体为准,见
     * FontFamily 类定义)
     * @param isBoldFont 是否加粗(详见 FontFamily 类定义)
     */
    @Override
    public int appendPrnStr(String text, int fontsize, boolean isBoldFont) throws RemoteException {
        log.info("call appendPrnStr");
        if (TextUtils.isEmpty(text)) {
            return ServiceResult.Printer_Wrong_Package;
        }
        if (startPrintIsRunning) return ServiceResult.Printer_Busy;
        int size;
        switch (fontsize) {
            case FontFamily.SMALL:
                size = 20;
                break;
            case FontFamily.MIDDLE:
                size = 24;
                break;
            case FontFamily.BIG:
                size = 30;
                break;
            default:
                size = 24;
                break;
        }
        int result = sdkPrinter.appendPrnStr(text, size, AlignEnum.LEFT, isBoldFont);

//        FontEntity font = new FontEntity(DotMatrixFontEnum.CH_SONG_24X24, DotMatrixFontEnum.ASC_MYuen_16X24);
//        font.setZoomX(false);
//        font.setZoomY(true);
//        LineOptionEntity ops = new LineOptionEntity();
//        ops.setUnderline(false);
//        ops.setMarginLeft(0);
//        int result = sdkPrinter.appendPrnStr(text, font, AlignEnum.LEFT, ops);

        if (result == SdkResult.Success) {
            return ServiceResult.Success;
        } else {
            return ServiceResult.Printer_AddPrnStr_Fail;
        }
    }


    /**
     * 设置打印图片数据
     * @param bitmap 图片位图
     */
    @Override
    public int appendImage(Bitmap bitmap) throws RemoteException {
        log.info("call appendImage");
        if (bitmap == null) return ServiceResult.Printer_Wrong_Package;
        if (startPrintIsRunning) return ServiceResult.Printer_Busy;
        log.debug("bitmap width {},height {}", bitmap.getWidth(), bitmap.getHeight());
//            if (bitmap.getWidth() > 380) return ServiceResult.Printer_OutOfMemory;
        if (bitmap.getWidth() > 384) {
            Matrix matrix = new Matrix();
            // 缩放原图
            matrix.postScale(384f / (float) bitmap.getWidth(), 384f / (float) bitmap.getWidth());
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }
        try {
//            File file = new File(Environment.getExternalStorageDirectory().getPath(), "tmp.jpg");
//            try {
//                file.createNewFile(); // 创建文件
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            OutputStream stream = new FileOutputStream(file);
//            bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream);
//            stream.flush();
//            stream.close();
            int result = sdkPrinter.appendImage(bitmap, AlignEnum.LEFT);
            if (result == SdkResult.Success) {
                return ServiceResult.Success;
            } else {
                return ServiceResult.Printer_AddImg_Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Printer_AddImg_Fail;
        }
    }


    /**
     * 打印机走纸
     * @param value 走纸量
     * @param unit  走纸单位(见 FeedUnit 类定义)
     */
    @Override
    public void feedPaper(int value, int unit) throws RemoteException {
        log.info("call feefPaper {}，{}", value, unit);
        if (startPrintIsRunning) return;
        try {
            if (value < 1) return;
            if (unit != FeedUnit.LINE && unit != FeedUnit.POINT) return;
            if (unit == FeedUnit.POINT) {
                sdkPrinter.appendPrnStr(" ", value, AlignEnum.LEFT, false);
            } else {
                sdkPrinter.appendPrnStr(" ", value * 24, AlignEnum.LEFT, false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 切纸补偿
     */
    @Override
    public void cutPaper() throws RemoteException {
        log.info("call cutPaper");
        if (startPrintIsRunning)
            return;
//        sdkPrinter.appendPrnStr(" ", Build.MODEL.equals(MachineModelUtils.G870) ? 80 : 150, AlignEnum.LEFT, false);
        int result = sdkPrinter.startPrint(true, new com.nexgo.oaf.apiv3.device.printer.OnPrintListener() {
            @Override
            public void onPrintResult(int i) {
                startPrintIsRunning = false;
            }
        });
        if (result == SdkResult.Success) {
            startPrintIsRunning = true;
        }
    }

    /**
     * 脚本打印
     * @param text    脚本打印内容，格式见附录6
     * @param options 脚本打印选项，JSON格式：width-整体打印宽度，默认384
     */
    @Override
    public int appendScript(String text, String options) throws RemoteException {
        log.info("call appendScript options:{} text:{}", options, text);
        if (false == GlobalDataHolder.getInstance().isSupportScrpitPrint())
            return ServiceResult.Printer_Fault;
        if (startPrintIsRunning)
            return ServiceResult.Printer_Busy;
        if (null == text || 0 == text.length())
            return ServiceResult.Printer_Wrong_Package;

        PrintScript.GlobalParam printScriptParam = new PrintScript.GlobalParam(sdkPrinter, context);

//        try {
        if (options != null) {
            JSONObject optionsJson = null;
            int width = 0;
            try {
                optionsJson = new JSONObject(options);
                width = optionsJson.getInt("width");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            if (width < 384 && width > 0)
                printScriptParam.printerWidth = width;
        }

        log.debug("PrinterScript generate scriptlist!");
        String[] scriptStrs = text.split("\n");
        for (String scriptStr : scriptStrs) {
            try {
                PrintScript script = PrintScript.create(scriptStr, printScriptParam);
                if (false == script.execute())
                    log.error("PrinterScript Execute fail! type:{} cmd:{},param:{}", script.type(), script.cmd(), script.param());
            } catch (Exception e) {
                e.printStackTrace();
                log.error("Deal Script Err!", e);
            }
        }
        return ServiceResult.Success;
    }
}
